package com.wstuo.common.jaas.service;

import java.io.IOException;
import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.annotation.Transactional;

import com.sun.security.auth.UserPrincipal;
import com.wstuo.common.security.service.IUserInfoService;
import com.wstuo.common.security.utils.AppConfigUtils;
import com.wstuo.common.util.AppliactionBaseListener;

/**
 * OPEN LDAP Login 验证方法
 * @author Administrator
 *
 */
public class OpenLDAPLoginModule implements LoginModule{
	private static final Logger LOGGER = Logger.getLogger(OpenLDAPLoginModule.class);

	private Boolean isAuthenticated = false;
	private CallbackHandler callbackHandler;
	private Subject subject;
    private UserPrincipal principal;
	private static final String JAAS_PATH =  AppConfigUtils.getInstance().getCustomJAASPath();
 	public static String getJasperPath() {
 		return JAAS_PATH;
 	}
    static{
        System.setProperty("java.security.krb5.conf", JAAS_PATH+"/krb5.ini");
    }
     
	public void initialize(Subject subject, CallbackHandler callbackHandler,
	      @SuppressWarnings("rawtypes") Map sharedState,@SuppressWarnings("rawtypes") Map options) {
	    this.subject = subject;
	    this.callbackHandler = callbackHandler;
	}

	@Transactional
	public boolean login() throws LoginException {
		Configuration.getConfiguration().refresh();
	    try {
	    	NameCallback nameCallback = new NameCallback("username");
	    	PasswordCallback passwordCallback = new PasswordCallback("password",false);
	    	final Callback[] calls = new Callback[] { nameCallback, passwordCallback };
	    	// 获取用户数据
	    	callbackHandler.handle(calls);
	    	String username = nameCallback.getName();
	    	String password = String.valueOf(passwordCallback.getPassword());
	    	//查询数据库验证用户
	    	ApplicationContext ctx =AppliactionBaseListener.ctx;
	    	IUserInfoService userInfoService = (IUserInfoService)ctx.getBean("userInfoService");
	    	if (userInfoService.ldapAuthAndUpdate(username, password)) {// 验证通过
	    		principal = new UserPrincipal(username);
	    		isAuthenticated = true;
	    	} else {
	    		isAuthenticated = false;
	    	}

	    } catch (IOException e) {
	    	LOGGER.error(e);
	    	isAuthenticated = false;
	    } catch (UnsupportedCallbackException e) {
	    	LOGGER.error(e);
	    	isAuthenticated = false;
	    }
	    return isAuthenticated;
	  }
	  /**
	   * 验证后的处理,在Subject中加入用户对象
	   */
	  public boolean commit() throws LoginException {
		  if (isAuthenticated) {
			  subject.getPrincipals().add(principal);
		  } else {
			  throw new LoginException("Authentication failure");
		  }
		  return isAuthenticated;
	  }

	  public boolean abort() throws LoginException {
		  return false;
	  }

	  public boolean logout() throws LoginException {
		  subject.getPrincipals().remove(principal);
		  principal = null;
	    return true;
	  }
}
